package com.analyst.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.analyst.dto.JobDTO;
import com.analyst.dto.ResultVO;
import com.analyst.entity.Job;
import com.analyst.service.IGraphService;
import com.analyst.service.ILogService;
import com.analyst.service.ITimeService;
import com.analyst.utils.DateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;


import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@CrossOrigin
@RestController
@RequestMapping("/icbc/index")
public class Controller {
    @Resource
    private ILogService logService;
    @Resource
    private ITimeService timeService;
    @Resource
    private IGraphService graphService;

    /**
     * 根据原始数据库中的数据，得到依赖图和关键路径（返回数据中也有pendingtime）
     * @param jobName
     * @return
     */
    @RequestMapping("/getGraphData/{jobName}")
    public ResultVO getGraphData(@PathVariable String jobName) {
        Map<String, Job> map = timeService.initJobsIntoMapFromDatabase();
        Job queryJob = map.get(jobName);
        timeService.calPendingTime(queryJob, map, true);
        Map<String, Job> jobMap = timeService.getJobsOnRoute(jobName, map);
        timeService.setCache(jobMap);
        List<Set> nodesAndEdges = timeService.getRoute(queryJob, map);
        return ResultVO.success(graphService.getGraphData(queryJob, nodesAndEdges));
    }

    @GetMapping("getJobRankList/{jobName}")
    public ResultVO getJobRankList(@PathVariable String jobName) {
        List<List<String>> jobRankList = timeService.getJobRankList(jobName);
        if (jobRankList==null) return ResultVO.failed("未找到该作业信息");
        return ResultVO.success(jobRankList);
    }

    /**
     * 根据更新节点的id集合和更新时间的集合，得到新的GraphData
     * @param updateJobIds
     * @param newEndTimeList
     * @return
     */
    @GetMapping("/parallelUpdateByConcreteTime/{updateJobIds}/{newEndTimeList}")
    public ResultVO parallelUpdateByConcreteTime(@PathVariable List<String> updateJobIds,
                                                 @PathVariable @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") List<Date> newEndTimeList) {
        // pengdingtime
        // 这个效率不高，当前前端实现的是查询一个节点，输出其依赖图，因此不用把数据库中所有节点的pendingtime都求出来
        // timeService.calPendingTimeMultRoot(databaseJobs);
        Map<String, Job> map = timeService.initJobsIntoMap();
        // 因为是在显示依赖图的情况下修改节点的结束时间，且图上只有一个根节点
        // 所以传入的要更新的节点不可能属于由另一个根节点延伸出的依赖图中
        // 因此根据要更新的节点的第一个节点，查出当前依赖图中的根节点即可
        Job endJob = timeService.getEndJob(map.get(updateJobIds.get(0)));
        Map<String, Job> jobMap = timeService.getJobsOnRoute(endJob.getId(), map);
        for (String updateJobId : updateJobIds) {
            jobMap.get(updateJobId).setUpdate(true);
        }
        timeService.resetUpdateStyle(updateJobIds, endJob, jobMap);

//        timeService.calPendingTime(endJob, true);
        String improveTimeForEndJob = timeService.parallelUpdateByConcreteTime(updateJobIds, newEndTimeList, jobMap);
        List<Set> nodesAndEdges = timeService.getRoute(endJob, jobMap);
        return ResultVO.success(graphService.getUpdatedGraphData(endJob, nodesAndEdges, improveTimeForEndJob));
    }

    @GetMapping("/get/{queryName}")
    public List<JobDTO> getList(@PathVariable String queryName) throws Exception {
        List<Job> databaseJobs = timeService.initJobsByDataBase();
        Map<String, Job> map = databaseJobs.stream().collect(Collectors.toMap(Job::getId, Function.identity()));
        Job queryJob = map.get(queryName);
        List<Job> jobs = timeService.getKeyRoute(queryJob);

        // Initialize the ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        return jobs.stream().map(job -> {
            // 过滤出两个集合的属性,转化为 list id 集合
            List<String> dependenciesIds = job.getDependencies().stream()
                    .map(Job::getId)
                    .collect(Collectors.toList());

            List<String> nextListIds = job.getNextList().stream()
                    .map(Job::getId)
                    .collect(Collectors.toList());

            // 对 v 进行处理
            JobDTO jobDTO = BeanUtil.toBean(job, JobDTO.class,
                    CopyOptions.create().setFieldValueEditor((k, v) -> {
                        if (k.equals("nextList")) {
                            return nextListIds;
                        } else if (k.equals("dependencies")) {
                            return dependenciesIds;
                        }
                        return v;
                    }));

            return jobDTO;
        }).collect(Collectors.toList());

    }

}
